-
Notifications
You must be signed in to change notification settings - Fork 590
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ERC: Tap to Pay #686
base: master
Are you sure you want to change the base?
Add ERC: Tap to Pay #686
Conversation
ERCS/erc-_____.md
Outdated
1. The merchant is running an app on their point-of-sale (PoS) system that allows initiating a checkout flow. | ||
1. When the customer is done ordering, the merchant goes through the checkout flow up and triggers a payment request. | ||
1. The merchant app calls the `requestContactlessPayment` RPC method with the expected payload. | ||
1. The merchant's device emits an NFC signal via host card emulation ([HCE](https://developer.android.com/develop/connectivity/nfc/hce)) for the customer’s device to read. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this done via the Ethereum provider receiving the above call? So is it assumed the provider needs to be running on device?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
ERCS/erc-_____.md
Outdated
1. When the customer is done ordering, the merchant goes through the checkout flow up and triggers a payment request. | ||
1. The merchant app calls the `requestContactlessPayment` RPC method with the expected payload. | ||
1. The merchant's device emits an NFC signal via host card emulation ([HCE](https://developer.android.com/develop/connectivity/nfc/hce)) for the customer’s device to read. | ||
1. The customer, running their wallet software of choice, reads the NFC signal. The customer’s wallet constructs the necessary transaction(s) to execute the onchain checkout. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I don't know much about this, why couldn't we just do a normal eth_sendTransaction or wallet_sendCalls via an NFC channel?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We had some sluggish performance transmitting the NFC message with larger payloads and decided to use a relayer for a shorter URI.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could still use a relayer by using wallet_sendCalls + something like a nfcRelay
capability
ERCS/erc-_____.md
Outdated
1. Upon successful onchain execution of these transactions, the checkout is complete. | ||
|
||
#### Use Case 2: Peer-to-peer Sends | ||
1. Alice requests a payment on her wallet app by emitting an NFC signal. The contents of the signal is an EIP-681 URI |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think 681 is possibly over specified on things like gas values. Wonder if we could align on something more minimal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're already using 681 heavily on send/receive flows on CB Wallet. We tried leaning into existing standards. What would you suggest could be better?
ERCS/erc-_____.md
Outdated
- 1 means the URI is an EIP-681-compliant payload. | ||
- 2 means the URI points to an HTTP relayer, where the response of the relayer is either a JSON object with the transaction data already encoded as a 0x string, or a message for the customer to sign. The customer wallet is responsible for constructing, signing and submitting the transaction/message. | ||
|
||
- `uri` represents either the EIP-681-compliant payload or the relayer endpoint to query for the JSON payload. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like 681 URI is not widely adopted and is mostly useful when you can share a string with someone and not a whole payload.
But here we control the channel so I'm again wondering why not just use existing wallet RPCs to describe what we want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, it's not widely adopted. Open to any other suggestions 🙏
Thanks for the quick review @wilsoncusack ❤️ |
Co-authored-by: Andrew B Coathup <[email protected]>
Co-authored-by: Andrew B Coathup <[email protected]>
ERCS/erc-7798.md
Outdated
``` | ||
|
||
##### EIP-712 | ||
```ts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think 712 is available on this repository. What's the proper way to do a relative ref here?
- Some fixes on automated PR feedback - Remove relative links - Adds copyright waiver
}); | ||
``` | ||
|
||
### Type 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are offchain signatures supported for type 1? i dont think it's covered by 681?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, we covered them with the relayed URI. You can basically pass down any long-form payload / set of batched transactions for EIP-3009 or permit2
} | ||
``` | ||
|
||
**[EIP-712](https://eips.ethereum.org/EIPS/eip-712) Message (offline signature)** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm i guess sendCalls wouldnt work for getting offchain signatures
overall i agree with Wilson's feedback -- feel like it would be cleanest if we could just transmit the usual RPC request over the NFC channel. would be easier for devs to reason about and i think it would be easier to adopt than extending the 1193 provider. seems like there were issues transmitting larger messages through nfc, and it makes me wonder if that should just be an issue for the provider to resolve if the message is to be transmitted over NFC. that way the app dev can use the same interface as usual, and then the wallet maintainers resolve how to compress & transmit to wallet. |
When you mention the same interface you mend |
|
--- | ||
|
||
## Abstract | ||
This ERC defines a standard for contactless payment transactions that can allow for interoperable customer to merchant onchain payments, regardless of the wallets the customer and merchant are using. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The abstract should contain enough detail to give the reader a high-level (but still technical) overview of how your proposal accomplishes its goals.
- An optional mechanism for relaying large JSON payloads using a backend relayer | ||
|
||
|
||
```mermaid |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our renderer doesn't support mermaid. Please replace it with an image in your assets directory (preferably an SVG.)
|
||
#### Use Case 2: Peer-to-peer Sends | ||
1. Alice requests a payment on her wallet app by emitting an NFC signal. The contents of the signal is an [ERC-681](erc-681.md) URI | ||
> []will this only work with 681? 681 has limitations, like receiver intent which would be great to solve too. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
> []will this only work with 681? 681 has limitations, like receiver intent which would be great to solve too. | |
<!-- will this only work with 681? 681 has limitations, like receiver intent which would be great to solve too. --> |
If you use HTML-style comments, the linter will make sure you replace them before going into Review.
### requestContactlessPayment | ||
The requestContactlessPayment method will be added as a standard method to the [EIP-1193 Ethereum Provider JavaScript API](eip-1193). | ||
|
||
This method takes in two parameters: `type` and `uri`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I usually recommend including a JSON Schema for any new API endpoints.
The commit b0b33c8 (as a parent of ecbfb71) contains errors. |
1. Bob then signs and submits the transaction onchain. | ||
1. Send flow is complete. | ||
|
||
### requestContactlessPayment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this have some prefix e.g. wallet_
?
### requestContactlessPayment | |
### wallet_requestContactlessPayment |
params: { | ||
type: 2, | ||
uri: "https://nfcrelay.xyz/paymentTxParams?uuid=1234-abcd-56678", | ||
verificationCode: "1234567890" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the purpose of verificationCode
and why can't its value be included in the uri
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess its a token/key that the wallet can use to verify the transaction received by the relayer endpoint is the same as the one send by the merchant
dappUrl?: string; | ||
dappName?: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a phishing vector. Recommend not including it at all (user knows what they tapped) and wallets should do their own security checks e.g. txn simulation.
**Regular Send** | ||
```ts | ||
{ | ||
payloadType: 'eip681'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What makes this a eip681 payload? The fields don't seem to map to EIP-681 very well.
window.ethereum.request({ | ||
method: 'requestContactlessPayment', | ||
params: { | ||
type: 1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest using strings for type instead of numbers. Specifically, type here should be erc681
and then for the relay perhaps a separate ERC could be defined for the relay design (and use that ERC number here). This allows easier future expansion to more types of in-NFC payloads and relayers without risking conflicting numbers. (ERC number is the type registry)
} | ||
} | ||
``` | ||
Upon submitting the transaction for the [ERC-681](erc-681.md) and contract call cases, if `rpcProxySubmissionParams` is present, then the transaction hash can be optionally submitted via a POST request to the submission URL. The body of the POST would have the following structure: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optionally? Why not required?
1. The merchant’s device then transmits the NFC relayer endpoint URI and verification code to the customer via any means | ||
1. The customer’s device then makes a GET request to the endpoint URI | ||
|
||
One of three payloads can be returned from the NFC relayer: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about a payload type where any arbitrary wallet RPC call can be included? Whether that's eth_sendTransaction
or more recent specs such as wallet_sendCalls
or wallet_grantPermissions
.
rpcProxySubmissionParams
could also do with a more general approach: sending the wallet RPC response directly.
Do you think expected error handling should be also included in the specs?
|
|
||
[ERC-681](erc-681.md) URIs were also permitted to enable possible direct peer to peer payments. It’s more likely that they’ll be occurring between two end user wallets rather than between a customer and a merchant, but it would be good to include in the event the dapp only requires a simple send transaction to execute the checkout. | ||
|
||
## Security Considerations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NFC isn’t end-to-end encrypted, so I think there’s a potential vulnerability to a relay attack. An adversary intercepts and forwards communication between a user and a merchant, basically extending the NFC range. To mitigate this, wallets should have security precautions like transaction simulation, a trusted merchants list, or spending limits.
See https://hackmd.io/VyxIMlk1SvCOpBpS6a_2uA?both for initial commentary on the standard